﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Linq;
using System.Globalization;

namespace Gmantis.Controls.DataGrid
{
    [TemplatePart(Name = "FilterOperation", Type = typeof(ComboBox)), TemplatePart(Name = "FilterBox", Type = typeof(TextBoxBase))]
    public class DataGridTextFilter : Control, IDataGridFilter, IDataGridFilterUnity, INotifyPropertyChanged
    {
        // Fields
        internal TextBoxBase _elementFilterBox;
        internal ComboBox _elementFilterOperation;
        private DataGridFilterState _filter;
        private string _filterText = "";
        internal bool _isLoaded;
        private DataGridFilterOperation _selectedOperation;
        private static List<DataGridTextFilterEntry> _supportedOperations;
        internal const string FilterBoxElementName = "FilterBox";
        internal const string FilterOperationElementName = "FilterOperation";
        public static readonly DependencyProperty FocusBrushProperty = DependencyProperty.Register("FocusBrush", typeof(Brush), typeof(DataGridTextFilter), null);
        public static readonly DependencyProperty InputBackgroundProperty = DependencyProperty.Register("InputBackground", typeof(Brush), typeof(DataGridTextFilter), null);
        public static readonly DependencyProperty InputForegroundProperty = DependencyProperty.Register("InputForeground", typeof(Brush), typeof(DataGridTextFilter), null);
        public static readonly DependencyProperty MouseOverBrushProperty = DependencyProperty.Register("MouseOverBrush", typeof(Brush), typeof(DataGridTextFilter), null);
        public static readonly DependencyProperty PressedBrushProperty = DependencyProperty.Register("PressedBrush", typeof(Brush), typeof(DataGridTextFilter), null);
        public static readonly DependencyProperty SelectedBackgroundProperty = DependencyProperty.Register("SelectedBackground", typeof(Brush), typeof(DataGridTextFilter), null);

        // Events
        public event EventHandler<PropertyChangedEventArgs<DataGridFilterState>> FilterChanged;
        public event PropertyChangedEventHandler PropertyChanged;

        // Methods
        public DataGridTextFilter()
        {
            base.DefaultStyleKey = typeof(DataGridTextFilter);
        }

        public void Clear()
        {
            if (this._isLoaded)
            {
                this.SelectedOperation = DataGridFilterOperation.Contains;
                this.FilterText = "";
                DataGridFilterState state = this._filter;
                DataGridFilterState state2 = (DataGridFilterState)(this._filter = null);
                if (this.FilterChanged != null)
                {
                    PropertyChangedEventArgs<DataGridFilterState> e = new PropertyChangedEventArgs<DataGridFilterState>
                    {
                        OldValue = state,
                        NewValue = state2
                    };
                    this.FilterChanged(this, e);
                }
            }
        }

        public void Create()
        {
            DataGridFilterState filter = this.GetFilter();
            if (filter != null)
            {
                DataGridFilterState state2 = this._filter;
                this._filter = filter;
                if (this.FilterChanged != null)
                {
                    PropertyChangedEventArgs<DataGridFilterState> e = new PropertyChangedEventArgs<DataGridFilterState>
                    {
                        OldValue = state2,
                        NewValue = this._filter
                    };
                    this.FilterChanged(this, e);
                }
            }
        }

        protected virtual DataGridFilterState GetFilter()
        {
            DataGridFilterState state = new DataGridFilterState();
            DataGridFilterInfo info = new DataGridFilterInfo
            {
                Value = this.FilterText,
                FilterOperation = this.SelectedOperation,
                FilterCombination = DataGridFilterCombination.None,
                FilterType = DataGridFilterType.Text
            };
            state.FilterInfo = new List<DataGridFilterInfo> { info };
            return state;
        }

        private T GetTemplateChild<T>(string childName, bool required, ref string errors) where T : class
        {
            DependencyObject templateChild = base.GetTemplateChild(childName);
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "template part", childName, templateChild, required, ref errors);
            return (templateChild as T);
        }

        private static Storyboard GetTemplateChildResource(FrameworkElement root, string resourceName, bool required, ref string errors)
        {
            return GetTemplateChildResource<Storyboard>(root, resourceName, required, ref errors);
        }

        private static T GetTemplateChildResource<T>(FrameworkElement root, string resourceName, bool required, ref string errors) where T : class
        {
            object child = root.Resources[resourceName];
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "resource", resourceName, child, required, ref errors);
            return (child as T);
        }

        public void Load(DataGridFilterState filterState)
        {
            this.SetFilter(filterState);
        }

        private void OnAfterApplyTemplate()
        {
            this._elementFilterOperation.DisplayMemberPath = "Label";
            this._elementFilterOperation.SelectedValuePath = "Operation";
            this._elementFilterOperation.ItemsSource = from op in SupportedOperations select op;
            Binding binding = new Binding
            {
                Mode = BindingMode.TwoWay
            };
            this._elementFilterOperation.SetBinding(ComboBox.SelectedValueProperty, binding.From<DataGridTextFilter>(this, x => x.SelectedOperation));
            Binding binding2 = new Binding
            {
                Mode = BindingMode.TwoWay
            };
            this._elementFilterBox.SetBinding(TextBoxBase.GTextProperty, binding2.From<DataGridTextFilter>(this, x => x.FilterText));
        }

        public override void OnApplyTemplate()
        {
            string errors = string.Empty;
            base.OnApplyTemplate();
            this._isLoaded = true;
            this._elementFilterBox = this.GetTemplateChild<TextBoxBase>("FilterBox", true, ref errors);
            this._elementFilterOperation = this.GetTemplateChild<ComboBox>("FilterOperation", true, ref errors);
            if (!string.IsNullOrEmpty(errors))
            {
                this._isLoaded = false;
                if ((base.Template != null) && !PlatformIndependent.IsInDesignMode(this))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Template cannot be applied to DataGridTextFilter.\nDetails: {0}", new object[] { errors }));
                }
            }
            else
            {
                this.OnAfterApplyTemplate();
            }
        }

        protected void RaisePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        protected virtual void SetFilter(DataGridFilterState filterState)
        {
            if ((((filterState != null) && (filterState.FilterInfo != null)) && ((filterState.FilterInfo.Count > 0) && (filterState.FilterInfo[0] != null))) && (filterState.FilterInfo[0].FilterType == DataGridFilterType.Text))
            {
                string str = filterState.FilterInfo[0].Value as string;
                this.SelectedOperation = filterState.FilterInfo[0].FilterOperation;
                this.FilterText = str ?? string.Empty;
            }
            else
            {
                this.SelectedOperation = DataGridFilterOperation.Contains;
                this.FilterText = "";
            }
        }

        // Properties
        public DataGridFilterState Filter
        {
            get
            {
                return this._filter;
            }
            set
            {
                if (this._filter != value)
                {
                    this._filter = value;
                    this.SetFilter(value);
                    this.RaisePropertyChanged("Filter");
                }
            }
        }

        public string FilterText
        {
            get
            {
                return this._filterText;
            }
            set
            {
                if (this._filterText != value)
                {
                    this._filterText = value;
                    this.Filter = this.GetFilter();
                    this.RaisePropertyChanged("FilterText");
                }
            }
        }

        public Brush FocusBrush
        {
            get
            {
                return (Brush)base.GetValue(FocusBrushProperty);
            }
            set
            {
                base.SetValue(FocusBrushProperty, value);
            }
        }

        public Brush InputBackground
        {
            get
            {
                return (Brush)base.GetValue(InputBackgroundProperty);
            }
            set
            {
                base.SetValue(InputBackgroundProperty, value);
            }
        }

        public Brush InputForeground
        {
            get
            {
                return (Brush)base.GetValue(InputForegroundProperty);
            }
            set
            {
                base.SetValue(InputForegroundProperty, value);
            }
        }

        public Brush MouseOverBrush
        {
            get
            {
                return (Brush)base.GetValue(MouseOverBrushProperty);
            }
            set
            {
                base.SetValue(MouseOverBrushProperty, value);
            }
        }

        public Brush PressedBrush
        {
            get
            {
                return (Brush)base.GetValue(PressedBrushProperty);
            }
            set
            {
                base.SetValue(PressedBrushProperty, value);
            }
        }

        public Brush SelectedBackground
        {
            get
            {
                return (Brush)base.GetValue(SelectedBackgroundProperty);
            }
            set
            {
                base.SetValue(SelectedBackgroundProperty, value);
            }
        }

        public DataGridFilterOperation SelectedOperation
        {
            get
            {
                return this._selectedOperation;
            }
            set
            {
                if (this._selectedOperation != value)
                {
                    this._selectedOperation = value;
                    this.Filter = this.GetFilter();
                    this.RaisePropertyChanged("SelectedOperation");
                }
            }
        }

        private static List<DataGridTextFilterEntry> SupportedOperations
        {
            get
            {
                _supportedOperations = new List<DataGridTextFilterEntry>();
                DataGridTextFilterEntry item = new DataGridTextFilterEntry
                {
                    Label = "Contains",
                    Operation = DataGridFilterOperation.Contains
                };
                _supportedOperations.Add(item);
                DataGridTextFilterEntry entry2 = new DataGridTextFilterEntry
                {
                    Label = "Starts With",
                    Operation = DataGridFilterOperation.StartsWith
                };
                _supportedOperations.Add(entry2);
                DataGridTextFilterEntry entry3 = new DataGridTextFilterEntry
                {
                    Label = "Ends With",
                    Operation = DataGridFilterOperation.EndsWith
                };
                _supportedOperations.Add(entry3);
                DataGridTextFilterEntry entry4 = new DataGridTextFilterEntry
                {
                    Label = "Equals",
                    Operation = DataGridFilterOperation.Equal
                };
                _supportedOperations.Add(entry4);
                DataGridTextFilterEntry entry5 = new DataGridTextFilterEntry
                {
                    Label = "Not Equals",
                    Operation = DataGridFilterOperation.NotEqual
                };
                _supportedOperations.Add(entry5);
                return _supportedOperations;
            }
        }
    }
}
